import 'dart:io';
import 'dart:math';
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:card_swiper/card_swiper.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:html/dom.dart' as dom;
import 'package:share_plus/share_plus.dart';
import 'package:shirne_dialog/shirne_dialog.dart';
import 'package:url_launcher/url_launcher.dart';

import '../../tbicons.dart';
import '../../utils/api.dart';
import '../../utils/logger.dart';
import '../../utils/tools.dart';
import '../../widgets/tags/empty.dart';
import '../../widgets/tags/icon.dart';

import '../../models/article_model.dart';
import '../../application.dart';

class DetailPage extends StatefulWidget {
  final String? channel;
  final int? id;
  final Object? temp;

  DetailPage({Key? key, required Map<String, dynamic> arguments})
      : channel = arguments['channel'],
        id = arguments['id'],
        temp = arguments['temp'],
        super(key: key);

  @override
  State<DetailPage> createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {
  bool isLoading = true;
  ArticleModel? article;

  String title = '';
  String cover = '';
  String url = '';
  List<String> contentImages = [];

  bool isFavourite = false;
  bool isDigg = false;

  late ScrollController _scrollController;
  bool titleMode = false;
  double swipeHeight = 300;

  @override
  void initState() {
    super.initState();

    if (widget.temp != null) {
      if (widget.temp is Map<String, dynamic>) {
        var art = widget.temp as Map<String, dynamic>;
        title = art['title'] ?? '';
        cover = art['cover'] ?? '';
      } else if (widget.temp is ArticleModel) {
        article = widget.temp as ArticleModel;
        title = article!.title;
        cover = article!.cover;
      }
    }

    _scrollController = ScrollController();
    _scrollController.addListener(_onScroll);

    if (widget.id != null) {
      _loadData();
    }
  }

  bool get _hasContent => article?.content.isNotEmpty ?? false;

  _onScroll() {
    if (_scrollController.offset > swipeHeight - 50) {
      if (!titleMode && article != null) {
        setState(() {
          titleMode = true;
        });
      }
    } else {
      if (titleMode) {
        setState(() {
          titleMode = false;
        });
      }
    }
  }

  bool onAnchorTap(String url) {
    if (url.isEmpty || url.startsWith('#')) return false;
    if (kIsWeb) {
      launchUrl(Uri.parse(url));
    } else if (Platform.isAndroid || Platform.isIOS) {
      app.route('/web', arguments: {'url': url});
    } else {
      launchUrl(Uri.parse(url));
    }
    return true;
  }

  void onImageTap(ImageMetadata data) {
    if (data.sources.isEmpty) return;

    MyDialog.imagePreview(
      data.sources.map((t) => t.url).toList(),
      currentImage: data.sources.first.url,
    );
  }

  dom.Element getParent(dom.Element node) {
    if (node.parent == null) {
      return node;
    }
    return node.parent!;
  }

  void getImages(dom.Element? tree) {
    if (tree == null) return;
    if (tree.localName == 'img') {
      final src = tree.attributes['src'] ?? '';
      if (src.isNotEmpty && !contentImages.contains(src)) {
        contentImages.add(src);
      }
    } else if (tree.children.isNotEmpty) {
      for (var item in tree.children) {
        getImages(item);
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    swipeHeight = MediaQuery.of(context).size.width * 0.6;
    final colorScheme = Theme.of(context).colorScheme;
    final titleShadows = [
      BoxShadow(
        color: colorScheme.shadow,
        offset: const Offset(1, 1),
        blurRadius: 1,
      ),
    ];
    return Scaffold(
      extendBodyBehindAppBar: true,
      body: CustomScrollView(
        controller: _scrollController,
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            backgroundColor: Colors.white,
            expandedHeight: swipeHeight,
            leading: IconButton(
              onPressed: () {
                app.back(context);
              },
              icon: TagIcon(
                Icons.arrow_back,
                size: 24,
                color: titleMode ? Colors.black87 : Colors.white,
                shadows: titleMode ? null : titleShadows,
              ),
            ),
            flexibleSpace: FlexibleSpaceBar(
              title: Text(
                title,
                maxLines: titleMode ? 1 : 2,
                overflow: TextOverflow.ellipsis,
                style: TextStyle(
                  color: titleMode ? Colors.black87 : Colors.white,
                  shadows: titleMode ? null : titleShadows,
                ),
              ),
              centerTitle: true,
              titlePadding:
                  const EdgeInsets.symmetric(horizontal: 25, vertical: 15),
              background: (article?.images == null || article!.images!.isEmpty)
                  ? Stack(
                      fit: StackFit.expand,
                      children: [
                        Tools.image(article?.cover),
                        BackdropFilter(
                          filter: ImageFilter.blur(
                            sigmaX: 5,
                            sigmaY: 5,
                          ),
                          child: Container(),
                        ),
                      ],
                    )
                  : _buildSwipe(context),
              collapseMode: CollapseMode.parallax,
            ),
          ),
          SliverToBoxAdapter(
            child: Center(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: RichText(
                  text: TextSpan(
                    children: [
                      const TextSpan(text: '类目:'),
                      if (article != null)
                        TextSpan(text: article!.cateId.toString()),
                      const TextSpan(text: ' 发布日期:'),
                      if (article != null)
                        TextSpan(
                          text: Tools.formatDateFromTimestamp(
                            article!.createTime,
                          ),
                        ),
                      const TextSpan(text: ' 浏览:'),
                      if (article != null)
                        TextSpan(text: article!.views.toString()),
                    ],
                    style: Theme.of(context).textTheme.bodySmall,
                  ),
                  softWrap: false,
                ),
              ),
            ),
          ),
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.all(10),
              child: ConstrainedBox(
                constraints: const BoxConstraints(minHeight: 400),
                child: AnimatedSwitcher(
                  duration: const Duration(milliseconds: 500),
                  child: _hasContent
                      ? HtmlWidget(
                          article!.content,
                          onTapUrl: onAnchorTap,
                          onTapImage: onImageTap,
                          // extensions: [
                          //   OnImageTapExtension(
                          //     onImageTap: onImageTap,
                          //   ),
                          // ],
                        )
                      : (isLoading
                          ? const Center(
                              child: CircularProgressIndicator(
                                strokeWidth: 2,
                              ),
                            )
                          : const TagEmpty(
                              '暂无内容~',
                              icon: null,
                            )),
                ),
              ),
            ),
          ),
        ],
      ),
      bottomNavigationBar: BottomAppBar(
        shape: RoundTopShape(15),
        elevation: 8,
        color: colorScheme.surface,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            TextButton.icon(
              onPressed: () {
                if (article == null) return;
                app.route(
                  '/channel/comment',
                  arguments: {
                    'article_id': article!.id,
                    'title': article?.title,
                  },
                );
              },
              icon: Icon(
                Tbicons.comment,
                color: colorScheme.onSurface,
              ),
              label: Padding(
                padding: const EdgeInsets.symmetric(vertical: 15),
                child: Text(
                  '${article?.comment}',
                  style: Theme.of(context).textTheme.bodySmall,
                ),
              ),
            ),
            TextButton.icon(
              onPressed: () {
                if (article == null) return;
                Share.share(url, subject: article?.title);
              },
              icon: Icon(
                Tbicons.share,
                color: colorScheme.onSurface,
              ),
              label: Padding(
                padding: const EdgeInsets.symmetric(vertical: 15),
                child: Text('分享', style: Theme.of(context).textTheme.bodySmall),
              ),
            ),
            TextButton.icon(
              onPressed: _sendFav,
              icon: Icon(
                isFavourite ? Tbicons.likefill : Tbicons.like,
                color: isFavourite ? Colors.redAccent : colorScheme.onSurface,
              ),
              label: Padding(
                padding: const EdgeInsets.symmetric(vertical: 15),
                child: Text('收藏', style: Theme.of(context).textTheme.bodySmall),
              ),
            ),
            TextButton.icon(
              onPressed: _sendDigg,
              icon: Icon(
                isDigg ? Tbicons.appreciatefill : Tbicons.appreciate,
                color: isDigg ? colorScheme.primary : colorScheme.onSurface,
              ),
              label: Padding(
                padding: const EdgeInsets.symmetric(vertical: 15),
                child: Text(
                  '${article?.digg}',
                  style: Theme.of(context).textTheme.bodySmall,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  _buildSwipe(BuildContext context) {
    return Swiper(
      itemBuilder: (BuildContext context, idx) {
        return Tools.image(article!.images![idx].image);
      },
      itemCount: article?.images?.length ?? 0,
      control: const SwiperControl(),
    );
  }

  _loadData() async {
    Api.post('article/view', {'id': widget.id!}).then((result) {
      var data = result.data;
      if (data == null) return;
      if (!mounted) return;
      setState(() {
        var pData = result.data!['article'];
        pData['images'] = result.data!['images'];
        article = ArticleModel.fromJson(pData);
        title = article!.title;
        cover = article!.cover;
        logger.info([
          result.data?['url'],
          result.data?['is_favourite'],
          result.data?['digged'],
        ]);

        url = result.data?['url'] ?? 'https://www.shirne.com';
        isFavourite = (result.data?['is_favourite'] ?? 0) > 0;
        isDigg = (result.data?['digged'] ?? 0) > 0;
        isLoading = false;
      });
    });
  }

  _sendFav() async {
    if (article == null) return;
    final result = await (isFavourite ? _favRemove() : _favAdd());
    if (result.code == 1) {
      MyDialog.toast(result.message, iconType: IconType.success);
      setState(() {
        isFavourite = !isFavourite;
      });
    } else {
      MyDialog.toast(result.message);
      if (result.needLogin) {
        app.route('/login');
      }
    }
  }

  Future<Result> _favAdd() {
    return Api.post(
      'member.favourite/add',
      {'id': widget.id!, 'type': 'article'},
    );
  }

  Future<Result> _favRemove() {
    return Api.post(
      'member.favourite/remove',
      {'ids': widget.id!, 'type': 'article'},
    );
  }

  _sendDigg() async {
    if (article == null) return;
    final result = await Api.post('article/digg', {'id': widget.id!});
    if (result.code == 1) {
      MyDialog.toast('感谢支持', iconType: IconType.success);
      setState(() {
        isDigg = true;
        article!.digg = result.data?['digg'] ?? 1;
      });
    } else {
      MyDialog.toast(result.message);
      if (result.needLogin) {
        app.route('/login');
      }
    }
  }
}

class RoundTopShape extends NotchedShape {
  final double borderRadius;

  RoundTopShape(this.borderRadius);

  @override
  Path getOuterPath(Rect host, Rect? guest) {
    if (borderRadius <= 0) return Path()..addRect(host);

    return Path()
      ..moveTo(0, borderRadius)
      ..arcTo(
        Rect.fromCircle(
          center: Offset(borderRadius, borderRadius),
          radius: borderRadius,
        ),
        -pi,
        pi / 2,
        false,
      )
      ..lineTo(host.width - borderRadius, 0)
      ..arcTo(
        Rect.fromCircle(
          center: Offset(host.width - borderRadius, borderRadius),
          radius: borderRadius,
        ),
        -pi / 2,
        pi / 2,
        false,
      )
      ..lineTo(host.width, host.height)
      ..lineTo(0, host.height)
      ..close();
  }
}
